<?php

class Db
{
    const ALL = 2;
    const ROW = 1;
    const COL = 0;

    private $debug = false;
    private $db;
    private $table;

    static private $instance = null;

    public function __construct($dsn, $table = null, $debug = false)
    {
        if (!is_array($dsn))
            return FALSE;

        $this->db = mysqli_connect($dsn['host'], $dsn['username'], $dsn['password'], $dsn['dbname'], $dsn['port'], $dsn['socket']);
        if (!$this->db)
            return FALSE;

        $this->debug = $debug;
        $this->table = $table;

        return TRUE;
    }

    static public function getInstance($dsn = null, $table = null)
    {
        if (is_null(self::$instance))
            self::$instance = new Db($dsn, $table);

        return self::$instance;
    }

    public function __destruct()
    {
        $this->db->close();
    }

    public function __set($name, $value)
    {
        $this->$name = $value;
    }

    public function __get($name)
    {
        return $this->$name;
    }

    public function showDebug($op, $sql)
    {
        echo "$op: ", $sql, PHP_EOL, "<br />";
    }

    static public function exists($db, $table, $field = null, $value = null)
    {
        if ($field === null) {
            $sql = "select * from $table limit 1";
        } else if ($value === null) {
            $sql = "select $field from $table limit 1";
        } else {
            $sql = "select $field from $table where $field='$value' limit 1";
        }

       return $db->query($sql) === FALSE ? FALSE : TRUE;
    }

    public function istable($table)
    {
        if ($table === null)
            $table = $this->table;

        return $table;
    }

    public function create($fileds = array(), $table = null)
    {
        if (($table = $this->istable($table)) === null
                || Db::exists($this->db, $table))
            return FALSE;

        $sql = 'CREATE TABLE '.$table;
        $sql .= '('.implode(",", $fileds).');';

        if ($this->debug)
            $this->showDebug('create', $sql);

        return $this->db->query($sql);
    }

    public function add($fields = [], $values = null, $table = null)
    {
        if (($table = $this->istable($table)) === null ||
                ($count = count($fields)) == 0)
            return FALSE;

        $sql = 'INSERT INTO '.$table;

        if (!is_array($values)) {
            $sql .= ' ('.implode(',', array_keys($fields)).') ';
            $sql .= 'VALUES';
            $sql .= " ('".implode("','", $fields)."')";
        } else {
            $sql .= ' ('.implode(',', $fields).') ';
            $sql .= 'VALUES';

            foreach ($values as $val) {
                if (!is_array($val) || $count != count($val))
                    return FALSE;
                $sql .= " ('".implode("','", $val)."'),";
            }
            $sql = rtrim($sql, ",");
        }

        if ($this->debug)
            $this->showDebug('add', $sql);

       if ($this->db->query($sql))
           return $this->db->insert_id;

        return FALSE;
    }

    public function edit($fields = array(), $where = "", $table = null)
    {
        if (($table = $this->istable($table)) === null
                || count($fields) == 0)
            return FALSE;

        $sql = 'UPDATE '.$table. ' SET ';
        foreach ($fields as $key => $val) {
            $sql .= $key."='".$val."',";
        }
        $sql = rtrim($sql, ',').' where '.$where;

        if ($this->debug)
            $this->showDebug('edit', $sql);

       return $this->db->query($sql);
    }

    public function del($where, $table = null)
    {
        if (($table = $this->istable($table)) === null)
            return FALSE;

        $sql = 'DELETE FROM '.$table.' '.$where;

        if ($this->debug)
            $this->showDebug('del', $sql);

       return $this->db->query($sql);
    }

    public function query($sql, $type = Db::ALL)
    {
        $result = $this->db->query($sql);
        if (!$result)
            return FALSE;

        $data = array();
        while ($row = $result->fetch_array(MYSQLI_ASSOC)) {
            if ($type == Db::COL)
                return array_shift($row);
            else if ($type == Db::ROW)
                return $row;

            $data[] = $row;
        }

        return $data;
    }
}


/*
 * $db = Db::getInstance([
 *     'host' => 'localhost',
 *     'port' => '3306',
 *     'username' => 'root',
 *     'password' => '123123',
 *     'dbname' => 'blog'
 * ]);
 */

// print_r($db);

/*
 * $db->table = "test";
 * $db->create(array(
 *     'id integer primary key auto_increment',
 *     'name text not null',
 *     'age int not null',
 *     'sex int not null'
 * ));
 */

// $db->add(array('name' => 'kyo', 'age' => 14, 'sex' => 1));
// $db->add(array('name' => 'kyo'));
/*
 * $db->add(['name', 'age','sex'], [
 *     ['tom', 12, 1],
 *     ['kyo', 33, 2],
 *     ['mary', 12, 3],
 * ]);
 */

// $db->edit(array('name' => 'php'), 'id=1');

// print_r($db->query('select * from test', Db::ALL));
// print_r($db->query('select * from test', Db::ROW));
// print_r($db->query('select * from test', Db::COL));

